package com.refusea.train.domain.helper

import com.refusea.train.config.mvc.WebSession
import com.refusea.train.domain.cache.ClassGroupStudentCache
import com.refusea.train.domain.cache.ClassroomCache
import com.refusea.train.domain.cache.CourseCache
import com.refusea.train.domain.cache.UserCache
import com.refusea.train.domain.entity.ClassGroup
import com.refusea.train.domain.entity.User.Role.PRINCIPAL
import com.refusea.train.domain.ex.BizEx
import com.refusea.train.domain.req.ClassGroupReq
import com.refusea.train.domain.tx.ClassGroupTx
import com.refusea.train.domain.vo.PaginationVo
import com.refusea.train.mapper.ClassGroupMapper
import com.refusea.train.mapper.ClassGroupStudentMapper
import com.refusea.train.mapper.LessonScheduleMapper
import org.springframework.stereotype.Component

/**
 * @author Zhang Yan 2024/4/7
 **/
@Component
class ClassGroupHelper(
    private val classGroupMapper: ClassGroupMapper,
    private val classGroupStudentMapper: ClassGroupStudentMapper,
    private val classGroupStudentCache: ClassGroupStudentCache,
    private val courseCache: CourseCache,
    private val userCache: UserCache,
    private val classroomCache: ClassroomCache,
    private val classGroupTx: ClassGroupTx,
    private val lessonScheduleMapper: LessonScheduleMapper,
) {

    private val limit = 10

    fun query(req: ClassGroupReq): PaginationVo {

        req.schoolId = WebSession.user().schoolId
        req.calculateOffset(limit)


        val total = classGroupMapper.count(req)
        if (total == 0) {
            return PaginationVo.empty(req.page, limit)
        }

        return PaginationVo(
            req.page,
            limit,
            total,
            if (req.offset >= total) {
                emptyList()
            } else {
                val classGroups = classGroupMapper.query(req)
                classGroups.forEach {
                    it.course = courseCache.get(it.courseId)
                    it.students = classGroupStudentCache.students(it.id)
                        .mapNotNull { id -> userCache.get(id) }
                    it.classroom = classroomCache.get(it.classroomId)
                }
                classGroups
            }
        )
    }

    fun save(classGroup: ClassGroup): Int {

        if (classGroup.schoolId != 0 && classGroup.schoolId != WebSession.user().schoolId) {
            throw BizEx.of("参数异常，请重新登录")
        }
        if (classGroup.studentIds.isNullOrEmpty()) {
            throw BizEx.of("参数错误：学员列表为空")
        }

        if (classGroup.schoolId == 0) {
            classGroup.schoolId = WebSession.user().schoolId
        }

        val id = if (classGroup.id == 0) {
            classGroupTx.insert(classGroup)
        } else {
            0
        }

        if (id > 0) {
            classGroupStudentCache.invalidate(classGroup.id)
        }

        return id
    }

    fun delete(id: Int) {

        val user = WebSession.user()
        if (user.role != PRINCIPAL) {
            throw BizEx.of("权限不足，无法删除班级")
        }

        val classGroup = classGroupMapper.select(id) ?: throw BizEx.of("班级不存在")
        if (classGroup.schoolId != user.schoolId) {
            throw BizEx.of("参数异常，请重新登录")
        }

        if (classGroup.confirmedLessons > 0) {
            throw BizEx.of("班级已开始上课，无法删除")
        }

        if (classGroup.completed) {
            throw BizEx.of("班级已结课，无法删除")
        }

        classGroup.studentIds = classGroupStudentMapper.students(classGroup.schoolId, classGroup.id)
        if (classGroup.studentIds.isNullOrEmpty()) {
            throw BizEx.of("班级没有学员，无法删除")
        }

        if (lessonScheduleMapper.firstByClassGroupId(classGroup.schoolId, classGroup.id) != null) {
            throw BizEx.of("班级已经排课，无法删除")
        }

        classGroupTx.delete(classGroup)
    }
}
